/**
 * 
 */
package featureautomate.structure;

import java.util.ArrayList;
import java.util.HashMap;



/**
 * @author D.Abdelali
 *
 */
public class Automate {
	
	
	private HashMap<String,Event> events;
	private HashMap<String,State> states;
	private ArrayList<Service> services;
	private HashMap<String,State> finals;
	private HashMap<String,String> commandes;
	private State init;
	/**
	 * @param events
	 * @param states
	 * @param services
	 * @param finals
	 * @param init
	 */
	
	
	public Automate() {

		this.events = new HashMap<>();
		this.states = new HashMap<>();
		this.services = new ArrayList<>();
		this.finals = new HashMap<>();
		this.commandes = new HashMap<>();
		this.init = null;
	}
	/**
	 * @param events
	 * @param states
	 * @param services
	 * @param finals
	 * @param init
	 */
	public Automate(HashMap<String, Event> events,
			HashMap<String, State> states, ArrayList<Service> services,
			HashMap<String, State> finals, State init,
			HashMap<String,String> commandes) {
		
		this.events = events;
		this.states = states;
		this.services = services;
		this.finals = finals;
		this.init = init;
		this.commandes = commandes;
	}
	/**
	 * @return the events
	 */
	public HashMap<String,Event> getEvents() {
		return events;
	}
	/**
	 * @param events the events to set
	 */
	public void setEvents(HashMap<String,Event> events) {
		this.events = events;
	}
	/**
	 * @return the states
	 */
	public HashMap<String,State> getStates() {
		return states;
	}
	/**
	 * @param states the states to set
	 */
	public void setStates(HashMap<String,State> states) {
		this.states = states;
	}
	/**
	 * @return the services
	 */
	public ArrayList<Service> getServices() {
		return services;
	}
	/**
	 * @param services the services to set
	 */
	public void setServices(ArrayList<Service> services) {
		this.services = services;
	}
	/**
	 * @return the finals
	 */
	public HashMap<String,State> getFinals() {
		return finals;
	}
	/**
	 * @param finals the finals to set
	 */
	public void setFinals(HashMap<String,State> finals) {
		this.finals = finals;
	}
	/**
	 * @return the init
	 */
	public State getInit() {
		return init;
	}
	/**
	 * @param init the init to set
	 */
	public void setInit(State init) {
		this.init = init;
	}
	
	public Automate clone(){
		
		Automate ret = new Automate();
		
		
		for(String e : events.keySet()){
			ret.getEvents().put(e,events.get(e).clone());
		}
		
		
		for(String e : states.keySet()){
			ret.getStates().put(e,new State(states.get(e).getName()));
			ret.getStates().get(e).setAction(states.get(e).getAction());
		}
		
		for(String e : states.keySet()){
			
			for(Transition t : states.get(e).getTransitions()){
				ret.getStates().get(e).getTransitions().add(new Transition(ret.getEvents().get(t.getEvent().getName()),ret.getStates().get(t.getState().getName())));
			}	
		}
		
		for(Service s : services){
			ret.getServices().add(s.clone());
		}
		
		for(String s : finals.keySet()){
			ret.getFinals().put(s, ret.getStates().get(s));
		}
		
		ret.setInit(ret.getStates().get(init.getName()));
		
		for(String s : commandes.keySet()){
			ret.getCommandes().put(s, commandes.get(s));
		}
		
		return ret;
	}
	
	/**
	 * @return the commandes
	 */
	public HashMap<String, String> getCommandes() {
		return commandes;
	}
	/**
	 * @param commandes the commandes to set
	 */
	public void setCommandes(HashMap<String, String> commandes) {
		this.commandes = commandes;
	}
	public void addEvent(featureautomate.structure.Event event){
		events.put(event.getName(), event);
	}
	
	public void addService(Service e){
		services.add(e);
	}
	
	public void addState(State e){
		states.put(e.getName(), e);
	}
	
	public void addFinals(State s){
		finals.put(s.getName(), s);
	}
	
	public boolean renameState(String s, String n){
		if(states.get(n) != null){
			return false;
		}
		
		states.put(n,new State(n));
		states.get(n).setAction(states.get(s).getAction());
		states.get(n).setTransitions((states.get(s).getTransitions()));
		
		for(String st : states.keySet()){
			for(Transition tr : states.get(st).getTransitions()){
				if(tr.getState().getName()==s){
					tr.setState(states.get(n));
				}
			}
		}
		
		if(init.getName() == s){
			init = states.get(n);
		}
		
		
		if(getFinals().containsKey(s)){
			addFinals(states.get(n));
			finals.remove(s);
		}
		
		
		states.remove(s);
		
		return true;
	}
	
	public String toString(){
		
		String ret = "" ;
		String newligne = System.getProperty("line.separator"); 
		
		ret += "events"+newligne;
		for(String  e : events.keySet()){
			if(events.get(e).isReset()){
				ret+="reset ";
			}
			ret+=e+newligne;
		}
		ret+="end"+newligne+newligne;
		
		
		ret += "services"+newligne;
		for(Service  e : getServices()){
			ret+=e.getName()+newligne;
		}
		ret+="end"+newligne+newligne;
		
		
		
		for(String s : getStates().keySet()){
			ret+="state "+s+newligne+" do{"+newligne;
			if(getStates().get(s).getAction() != null){
				ret += getStates().get(s).getAction().toString()+newligne;
			}
			ret+= " }"+newligne;
			for (Transition tr : getStates().get(s).getTransitions()){
				ret += tr.getEvent().getName()+" => "+tr.getState().getName()+newligne;
			}
			ret +="end"+newligne+newligne;
		}
		
		
		ret += "init : "+getInit().getName()+newligne+newligne;

		ret += "final : ";
		for(String s :getFinals().keySet()){
				ret+=s+" ";
		}
		ret+=newligne+newligne;
		
		return ret;
		
	}
	
	/**
     * @param event
     */
    public void deleteEvent2(String event) {
            // TODO Auto-generated method stub
            ArrayList<Integer> index ;
           
           
            for(String s : getStates().keySet()){
                    index = new ArrayList<>();
                    for(int i = getStates().get(s).getTransitions().size()-1; i>=0 ; i--){
                            if(getStates().get(s).getTransitions().get(i).getEvent().getName().equals(event)){
                                    index.add(i);
   
                                    //System.out.println("oui");
                            }
                    }
                    for(int i : index){
                            getStates().get(s).getTransitions().remove(i);
                    }
                   
                   
                   
            }
            getEvents().remove(event);
           
            deleteStateVide();
    }

	/**
	 * @param event
	 */
	public void deleteEvent(String event) {
		// TODO Auto-generated method stub
		ArrayList<Integer> index ;
		
		ArrayList<Transition> trans;
		for(String s : getStates().keySet()){
			index = new ArrayList<>();
			trans = new ArrayList<>();
			
			for(int i = getStates().get(s).getTransitions().size()-1; i>=0 ; i--){
				if(getStates().get(s).getTransitions().get(i).getEvent().getName().equals(event)){
					index.add(i);
					//System.out.println("oui");
				}
			}
			if(index.size()!=0){
				for(int i : index){
					trans.add(getStates().get(s).getTransitions().get(i));
					getStates().get(s).getTransitions().remove(i);
					
				}
				
			
				if(getStates().get(s).getTransitions().size()==0){
					for(String t : getStates().keySet()){
						index = new ArrayList<>();
						for(int i = getStates().get(t).getTransitions().size()-1; i>=0 ; i--){
							if(getStates().get(t).getTransitions().get(i).getState().getName().equals(s)){
								index.add(i);
							}
						}
						if(index.size()!=0){
							for(int i : index){
								for(Transition tr:trans){
									tr.setEvent(getStates().get(t).getTransitions().get(i).getEvent());
								}
								getStates().get(t).getTransitions().remove(i);
								for(Transition tr:trans){
									getStates().get(t).getTransitions().add(tr);
								}
								
							}
						}
						
					}
				}
			}
			
			
		}
		getEvents().remove(event);
		
		deleteStateVide();
	}
	
	public void deleteStateVide(){
		
		boolean bool = true;
		ArrayList<String> index = new ArrayList<>();
		for(String s : getStates().keySet()){
			bool = true;
			if(getStates().get(s).getTransitions().isEmpty()){
				for(String t : getStates().keySet()){
					for(Transition tr : getStates().get(t).getTransitions()){
						if(tr.getState().getName().equals(s)){
							bool = false;
						}
					}
				}
			}else{
				bool  = false;
			}
			
			if(bool){
				index.add(s);
			}
		}
		
		for(String s : index ){
			if(!getInit().getName().equals(s) && !getFinals().containsKey(s)){
				getStates().remove(s);
			}
		}
	}
}
